@tool
class_name NodeBase
extends GraphNode

#region 属性
@export var node_type:GameEnum.SkillNodeType = GameEnum.SkillNodeType.Control
@export var property_box_scene:PackedScene
@export_group("Parent")
@export var show_parent_port:bool = true
# -1 表示无限
@export var parent_max_connections:int = -1
@export var parent_port_allow_types:Array[GameEnum.SkillNodeType]
@export var parent: Label
@export_group("")
@export_group("Children")
@export var show_children_port:bool = true
# -1 表示无限
@export var children_max_connections:int = -1
@export var children_port_allow_types:Array[GameEnum.SkillNodeType]
@export var children: Label
@export_group("")
var visual_view:VisualView
var target:Node
var args:Dictionary
var parent_nodes:Array[NodeBase]
var children_nodes:Array[NodeBase]
var offest:Vector2
#endregion
#region 字段
#endregion
#region 信号
#endregion

#region 基类方法
#endregion
#region 公共方法
func init_node(visual_view:VisualView,target,args:Dictionary = {}):
	self.visual_view = visual_view
	self.target = target
	self.args = args
	parent_nodes = []
	children_nodes = []
	var connection_info:Dictionary = target.get_connection_info()
	parent_max_connections = connection_info.get("parent_max_connections",0)
	parent_port_allow_types = connection_info.get("parent_port_allow_types",[] as Array[GameEnum.SkillNodeType])
	children_max_connections = connection_info.get("children_max_connections",0)
	children_port_allow_types = connection_info.get("children_port_allow_types",[] as Array[GameEnum.SkillNodeType])
	set_slot_enabled_left(0,show_parent_port and parent_max_connections > 0)
	set_slot_enabled_right(0,show_children_port and children_max_connections > 0)
	for property_name in target.get_export_property_name_list():
		add_property(property_name)
	if target.get_export_property_name_list().size() > 0:
		var hs = HSeparator.new()
		self.add_child(hs)
		hs.owner = self
		hs.add_theme_stylebox_override("separator",StyleBoxEmpty.new())
func check_can_connect_parent(from_node:NodeBase) -> bool:
	if not show_parent_port:
		return false
	if not (from_node.node_type in parent_port_allow_types):
		return false
	if parent_max_connections != -1 and parent_nodes.size() >= parent_max_connections:
		return false
	return true
func check_can_connect_children(to_node:NodeBase) -> bool:
	if not show_children_port:
		return false
	if not (to_node.node_type in children_port_allow_types):
		return false
	if children_max_connections != -1 and children_nodes.size() >= children_max_connections:
		return false
	return true
func connect_parent(port:int,from_node:NodeBase):
	parent_nodes.append(from_node)
	target.reparent(from_node.target)
func connect_children(port:int,to_node:NodeBase):
	children_nodes.append(to_node)
	update_action_list()
	to_node.dragged.connect(on_child_node_dragged)
func disconnect_parent(port:int,from_node:NodeBase):
	parent_nodes.erase(from_node)
	var root_node = visual_view.get_root_node()
	if root_node:
		target.reparent(root_node.target)
func disconnect_children(port:int,to_node:NodeBase):
	to_node.dragged.disconnect(on_child_node_dragged)
	children_nodes.erase(to_node)
	update_action_list()
## 更新Action的子列表
func update_action_list():
	if target is SkillComposite:
		target.sub_actions.clear()
		for child in children_nodes:
			target.sub_actions.append(child.target)
	elif target is SkillControl:
		target.sub_actions.clear()
		for child in children_nodes:
			target.sub_actions.append(child.target)
	elif target is SkillAction:
		pass
	elif target is Skill:
		for child in children_nodes:
			target.action = child.target
## 更新ChildrenNode的顺序
func update_children_node_order():
	children_nodes.sort_custom(func(a:NodeBase,b:NodeBase):
		return a.position_offset.y < b.position_offset.y
		)
	update_action_list()
## 添加一条属性
func add_property(property_name:String) -> PropertyBox:
	if property_name in target:
		var property_box:PropertyBox = property_box_scene.instantiate()
		add_child(property_box)
		property_box.owner = self
		property_box.init(visual_view,target,property_name)
		set_slot_enabled_left(get_child_count() - 1,true)
		set_slot_enabled_right(get_child_count() - 1,false)
		return property_box
	else:
		return null
## 保存，先执行子类的保存，再保存自己的
func save():
	for child_node in children_nodes:
		child_node.save()
func destroy():
	if target:
		target.queue_free()
	queue_free()
#region 信号回调
## 子node被拖动
func on_child_node_dragged(from: Vector2, to: Vector2):
	update_children_node_order()
#endregion
#endregion
#region 私有方法
#endregion
#region 生命周期函数
func _ready() -> void:
	pass
#endregion
